package com.mybatis.basic.aop;

import java.lang.reflect.Method;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.mybatis.basic.MD5Utils;
import com.mybatis.basic.annotation.rediscache.RedisCache;
import com.mybatis.basic.service.RedisService;

/**
 * redis 缓存切面
 * @author Administrator
 *
 */
@Aspect
@Component
public class RedisCacheAOP {

	private static final Logger log = Logger.getLogger(RedisCacheAOP.class);

	@Resource
	private RedisService redisService;

	@Pointcut("@annotation(com.mybatis.basic.annotation.rediscache.RedisCache)")
	public void redisCache() {
		log.info("****** 执行RedisCache ******");
	}

	@Around("redisCache()")
	public Object redisCacheAround(ProceedingJoinPoint joinPoint) {
		Object obj = null;
		try {
			//得到代理方法
			Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
			//得到代理方法上的@RedisCache注解
			RedisCache redisCache = method.getAnnotation(RedisCache.class);
			//获取注解上的参数
			String name = redisCache.group();
			String key = redisCache.key();
	        int time = redisCache.expire();

	        //name 为空
	        if(!StringUtils.isEmpty(name)) {
	        	//如果key为空，使用方法[参数值-]MD5字符串作为key
	        	if(StringUtils.isEmpty(key)) {
	        		//得到参数值
					Object[] args = joinPoint.getArgs();
					//生成key
		        	key = createKey(args);
	        	}
				obj = redisService.getObject(name, key, method.getReturnType());
				if(null==obj || obj.equals("")) {
					obj = joinPoint.proceed(joinPoint.getArgs());
				}
        		redisService.set(name, key, obj, time, method.getReturnType());
	        }else {//name 不为空
	        	//key 不为空
	        	if(!StringUtils.isEmpty(key)) {
	        		obj = redisService.getObject(key, method.getReturnType());
	        		if(null==obj || obj.equals("")) {
	        			obj = joinPoint.proceed(joinPoint.getArgs());
	        		}
	        		redisService.set(key, obj, time, method.getReturnType());
	        	}else {
	        		throw new NullPointerException("[@RedisCache ==> 写入缓存] group AND key 不能同时为空");
	        	}
	        }
	        /*
	         * 

	        if(StringUtils.isEmpty(name)) {
	        	//得到类名
				String clazzName = joinPoint.getTarget().getClass().getName();
				//得到方法名
				String methodName = method.getName();// joinPoint.getSignature().getName();
				log.info("clazzName="+clazzName+" - methodName="+methodName);
				name = clazzName+":"+methodName;
	        }
	        if(StringUtils.isEmpty(key)) {
	        	//得到参数值
				Object[] args = joinPoint.getArgs();
				//生成key
	        	key = createKey(args);
	        }
			log.info("*********redis-group:"+name+" - redis-key:"+key+"**************");

			obj = redisService.getObject(name, key, method.getReturnType());
			log.info("redis缓存结果："+obj);
			if(null==obj || obj.equals("")) {
				//执行方法 返回结果
				obj = joinPoint.proceed(joinPoint.getArgs());
				redisService.set(name, key, obj, time, method.getReturnType());
			}
			
				         */
		} catch (Throwable e) {
			//e.printStackTrace();
			log.error(e);
			try {
				//Cacha 连接失败时执行方法获取结果
				obj = joinPoint.proceed(joinPoint.getArgs());
			} catch (Throwable e1) {
				e1.printStackTrace();
				log.error(e1);
			}
		}
		return obj;
	}

	/**
	 * 生成redis-key 
	 * @param args 参数值
	 * @return key:参数值MD5串
	 */
	public String createKey(Object[] args) {
		StringBuilder value = new StringBuilder();
		for (Object obj : args) {
			value.append(obj);
			value.append("-");
		}
		return MD5Utils.strToMD5(value.toString());
	}
}
